package cn.hackcloud.demo.dubbo;

import cn.hackcloud.demo.dubbo.rpc.IUserService;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.MethodConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.rpc.service.GenericException;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 泛化调用消费者
 *
 * @author 10427
 */
class DubboGenericConsumer implements  GenericService{

    private ApplicationConfig applicationConfig;
    private RegistryConfig registryConfig;
    private Call call;

    public DubboGenericConsumer(Call call) {
        this.applicationConfig = new ApplicationConfig("consumer");
        this.registryConfig = new RegistryConfig("zookeeper://47.93.251.127:2181");
        this.call = call;
    }

    public <T> T genericInvoke(String methodName, Object[] args) {

        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
        reference.setApplication(applicationConfig);
        reference.setRegistry(registryConfig);
        reference.setInterface(IUserService.class.getName());
        reference.setGroup("hackcloud");
        reference.setVersion("1.0");
        reference.setAsync(false);
        List<MethodConfig> methodConfigList = new ArrayList<>();
        MethodConfig method = new MethodConfig();
        method.setName(methodName);
        method.setAsync(false);
        //指定事件回调方法
        method.setOnreturn(call);
        method.setOnreturnMethod("onReturn");
        method.setOnthrow(call);
        method.setOnthrowMethod("onThrow");
        method.setTimeout(5000);
        methodConfigList.add(method);
        reference.setMethods(methodConfigList);
        // 声明为泛化接口
        reference.setGeneric(true);

        //ReferenceConfig实例很重，封装了与注册中心的连接以及与提供者的连接，
        //需要缓存，否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。
        //API方式编程时，容易忽略此问题。
        //这里使用dubbo内置的简单缓存工具类进行缓存

        //ReferenceConfigCache cache = ReferenceConfigCache.getCache();
      ; //cache.get(reference);
        // 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用

        int len = args.length;
        String[] invokeParamTypes = new String[len];
        Object[] invokeParams = new Object[len];
        for (int i = 0; i < len; i++) {
            invokeParams[i] = args[i];
            invokeParamTypes[i] = invokeParams[i].getClass().getName();
        }
        System.out.println(methodName + "  " + invokeParamTypes[0] + " " + invokeParams[0]);
        return (T)  reference.get().$invoke(methodName, invokeParamTypes, invokeParams);
    }


    @Override
    public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException {
        return genericInvoke(method,args);
    }
}
